package com.yanqu.road.server.cmd.player;

import com.yanqu.road.entity.enums.*;
import com.yanqu.road.entity.log.LogLogin;
import com.yanqu.road.entity.player.PlayerState;
import com.yanqu.road.entity.player.UserInfo;
import com.yanqu.road.entity.player.UserMarriageData;
import com.yanqu.road.entity.servercenter.ChannelVersion;
import com.yanqu.road.entity.servercenter.GameEditLimit;
import com.yanqu.road.entity.servercenter.ServerInfo;
import com.yanqu.road.entity.task.args.union.UnionActivityTaskArgs;
import com.yanqu.road.logic.config.GameConfig;
import com.yanqu.road.message.YanQuMessage;
import com.yanqu.road.pb.login.LoginProto;
import com.yanqu.road.server.GameServer;
import com.yanqu.road.server.agent.inter.AgentPlayer;
import com.yanqu.road.server.command.Cmd;
import com.yanqu.road.server.command.Command;
import com.yanqu.road.server.gameplayer.GamePlayer;
import com.yanqu.road.server.gameplayer.module.activity.ActivityModule;
import com.yanqu.road.server.gameplayer.module.activity.coupon.CouponActivityModule;
import com.yanqu.road.server.gameplayer.module.activity.lottery.ActivityLotteryModule;
import com.yanqu.road.server.gameplayer.module.activity.oldplayerreturn.OldPlayerReturnModule;
import com.yanqu.road.server.gameplayer.module.patrons.PatronsModule;
import com.yanqu.road.server.gameplayer.module.player.*;
import com.yanqu.road.server.gameplayer.module.rebate.ChinaRebateModule;
import com.yanqu.road.server.gameplayer.module.rebate.RebateModule;
import com.yanqu.road.server.gameplayer.module.recharge.GoldTokenRechargeModule;
import com.yanqu.road.server.gameplayer.module.retrieveReward.RecoveryRewardModule;
import com.yanqu.road.server.logic.activity.condition.coupon.CouponNotifyArgs;
import com.yanqu.road.server.logic.activity.condition.recharge.potential.PotentialArg;
import com.yanqu.road.server.logic.mail.MailManager;
import com.yanqu.road.server.manger.*;
import com.yanqu.road.server.manger.activity.dafuweng.DaFuWengMgr;
import com.yanqu.road.server.manger.activity.dunhuangshiku.DunHuangShiKuMgr;
import com.yanqu.road.server.manger.activity.lottery.ActivityLotteryMgr;
import com.yanqu.road.server.manger.activity.oldplayerreturn.OldPlayerReturnMgr;
import com.yanqu.road.server.manger.config.HideGoodsMgr;
import com.yanqu.road.server.manger.cross3.ChannelActivitySwitchMgr;
import com.yanqu.road.server.manger.log.AutoLogMgr;
import com.yanqu.road.server.manger.log.LogMgr;
import com.yanqu.road.server.manger.maidian.UserBagGoodsChangeMgr;
import com.yanqu.road.server.manger.player.DestroyRoleMgr;
import com.yanqu.road.server.manger.player.UserMgr;
import com.yanqu.road.server.manger.player.GamePlayerMgr;
import com.yanqu.road.server.manger.sacrifice.SacrificeMgr;
import com.yanqu.road.server.manger.system.ActivityIgnoreMgr;
import com.yanqu.road.server.manger.system.MiniGameConfigMgr;
import com.yanqu.road.server.manger.system.SystemSwitchMgr;
import com.yanqu.road.server.protocol.GameErrorCode;
import com.yanqu.road.server.protocol.Protocol;
import com.yanqu.road.server.webservice.GamePublicFunction;
import com.yanqu.road.utils.LocalDateTimeHelper;
import com.yanqu.road.utils.YanQuMessageUtils;
import com.yanqu.road.utils.date.DateHelper;
import com.yanqu.road.utils.property.Property;
import com.yanqu.road.utils.property.PropertyHelper;
import com.yanqu.road.utils.string.StringUtils;
import io.netty.channel.ChannelHandlerContext;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;

import java.math.BigInteger;
import java.util.Date;

@Cmd(code = Protocol.S_PLAYER_LOGIN, desc = "玩家登录")
public class LoginGameCmd implements Command {

    protected static Logger log = LogManager.getLogger(LoginGameCmd.class.getName());

    @Override
    public void execute(ChannelHandlerContext ctx, YanQuMessage packet) throws Exception {
        int ret = 0;
        ret = GamePublicFunction.loginCheckGameServerMemory(packet.getPlayerId());
        if(0 != ret){
            log.error("LoginGame failed,memory high, userId = " + packet.getPlayerId());
            return;
        }
        GamePlayer player = GamePlayerMgr.getPlayer(packet.getPlayerId());
        if (null == player) {
            log.error("LoginGame failed, userId = " + packet.getPlayerId());
            return;
        }
        UserInfo userInfo = player.getUserInfo();
        //上次登录时间
        long lastLoginTime = userInfo.getLastLoginTime();

        if (!ServerListMgr.canLogin(GameServer.getInstance().getServerId(), player.getIp(),
                userInfo.isAdmin(), userInfo.getPlatformUserId())) {
            ret = GameErrorCode.E_SERVER_MAINTAIN;
            sendResult(player, ret);
            return;
        }

        // 判断账号是否被封禁
        if (!ForbiddenMgr.canLogin(player.getIp()) || userInfo.getBlackListEndTime() > System.currentTimeMillis() ||
                ForbiddenMgr.isPlatformForbidden(player.getUserInfo().getPlatformUserId(), ePlatformForbiddenType.LOGIN.getType())) {
            ret = GameErrorCode.E_USER_FORBIDDEN;
        }

        // 元宝扣除封禁
        if(userInfo.getBlackListEndTime() == 4){
            ret = GameErrorCode.E_DEDUCT_INGOTS_NO_ENOUGH_FORBIDDEN;
            AgentPlayer.executeKillPlayer(userInfo.getUserId());
        }

        // 昵称为空说明还未创建角色
        if (StringUtils.isNullOrEmpty(userInfo.getNickName())) {
            ret = GameErrorCode.E_USER_NO_FOUND;
        } else {
            String nickName = new StringBuilder(userInfo.getNickName()).toString();
            nickName = StringUtils.clearHeadAndTailEmpty(nickName);

            //检测空白名称
            String checkName = StringUtils.clearBlankSpace(nickName);
            if(StringUtils.isNullOrEmpty(checkName)){
                String namePrefix = MultipleLanguageMgr.getContent(NameMgr.FORBIDDEN_NICKNAME_PREFIX, player.getLanguage());
                nickName = NameMgr.getForbiddenNickname(namePrefix);
                //发改名卡到邮件
                sendChangeNicknameGoods(player);
            }

            if (!userInfo.getNickName().equals(nickName)) {
                player.getModule(PlayerModule.class).setNickName(nickName);
            }
        }

        sendResult(player, ret);

        if (ret == 0) {
            ActivityModule activityModule = player.getModule(ActivityModule.class);
            activityModule.startChanges();

            DunHuangShiKuMgr.removeActivity(player);

            sendLockSystemList(player);

            HideGoodsMgr.syncHideGoods(player);

            player.sendLoginMessage();
            // 检测解锁
            player.getModule(PlayerModule.class).checkSystemOpen();

            player.getModule(OldPlayerReturnModule.class).playerReturn(lastLoginTime);   //回归触发要在登陆任务之前

            player.getModule(RecoveryRewardModule.class).loginRetrieveReward();
            doLoginNeedToDeal(player);
            rebate(player);
            // 在登录流程结束前要发数据，
            beforeLoginSuccessSend(player);
            //推送活动屏蔽数据
            ActivityIgnoreMgr.syncActivityIgnore(player);
            //登录流程结束
            player.sendPacket(Protocol.U_LOGIN_LAST_MARK, LoginProto.LoginLastMarkMsg.newBuilder());

            player.afterLogin();
            // 登录更新facebook follow值
            player.notifyListener(eGamePlayerEventType.FaceBookFunFollowNum.getValue(), ServerListMgr.getFbFollowCount());
            player.notifyListener(eGamePlayerEventType.VipLevel.getValue(), VipMgr.getVipLv(userInfo.getVipExp()));
            player.notifyListener(eGamePlayerEventType.RechargePotentialAnd.getValue(), new PotentialArg(true, 0));
            player.notifyListener(eGamePlayerEventType.RechargePotentialOr.getValue(), new PotentialArg(true, 0));

            player.notifyListener(eGamePlayerEventType.RechargeTrigger.getValue(), 0);
            //优惠券
            notifyCoupon(player);

            // 登录记录
            AutoLogMgr.add(new LogLogin(
                            player.getUserId(),
                            0,
                            player.getIp(),
                            player.getDeviceId(),
                            player.getUserInfo().getEarnSpeed().toString(),
                            player.getUserInfo().getSilver().toString(),
                            player.getModule(PatronsModule.class).getTotalPatronsAbility().toString()
            ));

            ServerInfo serverInfo = ServerListMgr.getServerInfo(GameServer.getInstance().getServerId());
            /* PushMgr.buildRoleLogin(player,serverInfo.getServerId(),serverInfo.getServerName());//角色登陆上报*/
            LightMsgMgr.sendLightMsgList(player);
            HideMallMgr.syncHideMallData(player);
            RechargeSwitchConfigMgr.syncRechargeOpenConfig(player);
            if (PlatformUserIdMgr.isPlatformUserIdPass(userInfo.getPlatformUserId())) {
                LogMgr.updatePlatfomUserLonginTime( userInfo.getPlatformUserId());

            }
            GamePlayerMgr.pushOnlineReport(player, serverInfo);
            // 同步跨地区活动开关
            ChannelActivitySwitchMgr.syncSwitch(player);
            // 登录事件
            DataAnalyticsMgr.trackUserLogin(player, lastLoginTime);
            //执行扣除元宝
            player.getModule(DeductIngotsModule.class).loginLogic();

            activityModule.finishChanges();
        }
    }

    private void sendLockSystemList(GamePlayer player) {
        player.sendPacket(Protocol.U_SYSTEM_LOCK_SYNC, SystemSwitchMgr.getLockSystemMsg());
    }

    //删档公测返利
    private void rebate(GamePlayer player) {
        //台湾1区返利
        if (GameServer.getInstance().getServerId() == 10100004 && System.currentTimeMillis() > 1596168000000L) {
            player.getModule(RebateModule.class).rebate2User();
        }
        player.getModule(ChinaRebateModule.class).rebateVipExp();
    }

    private void doLoginNeedToDeal(GamePlayer player) {
        dealTaskLogic(player);
    }

    private void dealTaskLogic(GamePlayer player) {
        //缓存上次登录时间
        player.setLastLoginTime(player.getUserInfo().getLastLoginTime());
        player.setState(PlayerState.ONLINE);
        //取消注销
        DestroyRoleMgr.cancelDestroyRole(player.getUserId());

        player.getModule(EarnSpeedModule.class).resetDay();
        player.notifyListener(eGamePlayerEventType.LoginDays.getValue(), 0); // 活动登录任务检查
        player.getModule(EarnSpeedModule.class).loginAddSilver();
        //新玩家关注邮件奖励
        xcxFollowReward(player);
        //编辑限制奖励
        editLimitReward(player);
        updateLoginTime(player);
        player.getModule(RechargeModule.class).loginLogic();
        player.getModule(GoldTokenRechargeModule.class).loginLogic();
        player.getModule(ActivityModule.class).initRechargeConditionData();
        SacrificeMgr.taskRecordPlayerInfo(player);
        //处理联姻
        dealMarriage(player);
    }

    /**
     * 处理联姻
     *
     * @param player
     */
    private void dealMarriage(GamePlayer player) {
        //离线时联姻次数
        MarriageModule marriageModule = player.getModule(MarriageModule.class);
        UserMarriageData userMarriageData = marriageModule.getUserMarriageData();
        if (null != userMarriageData) {
            if (userMarriageData.getOfflineMarriageTimes() > 0) {//离线时联姻次数
                player.notifyListener(eGamePlayerEventType.MarriageTimes.getValue(), userMarriageData.getOfflineMarriageTimes());
                player.notifyListener(eGamePlayerEventType.UnionMarriageTimes.getValue(), new UnionActivityTaskArgs(UnionActivityTaskArgs.TYPE_ADD_VALUE, userMarriageData.getOfflineMarriageTimes(), player.getUserInfo().getUnionUid()));
                userMarriageData.setTotalMarriageTimes(userMarriageData.getTotalMarriageTimes() + userMarriageData.getOfflineMarriageTimes());
                userMarriageData.setOfflineMarriageTimes(0);
                player.getModule(MarriageModule.class).syncUserMarriageData();
                player.notifyListener(eGamePlayerEventType.MarriageTotalTimes.getValue(), userMarriageData);
            }
            int recordSize = marriageModule.getMarriageRecordList().size();
            if (userMarriageData.getTotalMarriageTimes() < recordSize) {
                userMarriageData.setTotalMarriageTimes(recordSize);
                player.getModule(MarriageModule.class).syncUserMarriageData();
                player.notifyListener(eGamePlayerEventType.MarriageTotalTimes.getValue(), userMarriageData);
            }
        }
    }


    private void updateLoginTime(GamePlayer player) {
        UserInfo userInfo = player.getUserInfo();
        Date lastLoginDate = new Date(userInfo.getLastLoginTime() * 1000);
        boolean uploadUser = false;
        if (!DateHelper.isToday(lastLoginDate)) {
            //记录用户登录到用户中心数据库，只记录一次
            LogMgr.addLogDayLogin(player.getUserId(), player.getModule(PlayerModule.class).getUserInfo().getRegisterTime(),
                    System.currentTimeMillis() / 1000, GameServer.getInstance().getServerId());

            uploadUser = true;
        }
        player.getModule(SecretVolumeModule.class).setLastLoginTime(System.currentTimeMillis());
        player.getUserInfo().setLastLoginTime(System.currentTimeMillis() / 1000);
        UserBagGoodsChangeMgr.addUserLoginTime(player.getUserId());
        if(uploadUser){
            //当天首次登录，上报一次
            UserMgr.addNeedUpdateToCrossMap(player.getUserId(), player.getUserInfo());
        }
    }


    private static void sendResult(GamePlayer player, int ret) {
        LoginProto.LoginRespMsg.Builder respMsg = ServerListMgr.getLoginResp(ret);
        respMsg.setRet(ret);
        respMsg.setSystemTime(System.currentTimeMillis() / 1000);
        respMsg.setTimeZone(LocalDateTimeHelper.getDefaultTimeZone());
        respMsg.setSystemNanoTime(System.currentTimeMillis());
        //合服了，配置要用用原先的服
        long serverId = player.getModule(PlayerModule.class).getUserInfo().getOriginalServerId();
        ServerInfo serverInfo = ServerListMgr.getServerInfo((int) serverId);
        if (serverInfo != null) {
            respMsg.setClientVer(serverInfo.getClientVerCode());
            ChannelVersion lastVersion = ChannelVersionMgr.getLastReleaseVersion(serverInfo.getChannelId(), player.getPhonePlatform(), player.getIp(), player.getUserInfo().isAdmin(), player.getUserInfo().getPlatformUserId());
            if (null != lastVersion) {
                respMsg.setClientMajorVer(lastVersion.getClientVersion());
            }
            ChannelVersion channelVersion = ChannelVersionMgr.getChannelVersion(serverInfo.getChannelId(), player.getPhonePlatform(), player.getClientCurVer());
            if (null != channelVersion) {
                respMsg.setIsTishen(channelVersion.isReview());
            }
        }
        YanQuMessage message = YanQuMessageUtils.buildMessage(Protocol.U_PLAYER_LOGIN, respMsg);
        GamePlayerMgr.sendPacket(player.getUserId(), message);
    }

    /**
     * 登录后操作
     */
    private void beforeLoginSuccessSend(GamePlayer player) {
        // 大富翁配置
        if (DaFuWengMgr.isActivityInShowTime()) {
            DaFuWengMgr.syncDataAndConfig(player);
        }
        //老玩家回归同步每日任务和其他
        if (OldPlayerReturnMgr.getActivity() != null){
            player.getModule(OldPlayerReturnModule.class).syncNewActivityData();
        }
        if (ActivityLotteryMgr.hasActivity()){
            player.getModule(ActivityLotteryModule.class).syncUserData();
        }
        MiniGameConfigMgr.syncConfig(player);
    }

    /**
    * 描述：新玩家301小游戏关注奖励
    * 作者：zrq
    * 时间：2022/1/19
    * 参数：
    玩家对象
    * 返回值：
    **/
    private void xcxFollowReward(GamePlayer player) {
        int channelId = ServerListMgr.getChannelId(GameServer.getInstance().getServerId());
        if (eChannelType.isWeixinXiaoChengxuChannel(channelId)) {
            if(player.getUserInfo().getLastLoginTime() <= 0) {
                ServerInfo serverInfo = ServerListMgr.getServerInfo(GameServer.getInstance().getServerId());
                if(serverInfo.getServerType() == 1){//提审服不发开服邮件
                    return;
                }
                Property reward = new Property(GameConfig.GAME_MONEY_INGOTS, BigInteger.valueOf(100));
                String title = "欢迎来到汴梁";
                String content = "亲爱的掌柜，欢迎您来到汴梁。为了方便您后续更加方便进入汴梁，可移步【微信小程序】搜索《叫我大掌柜》。" +
                        "进入游戏后点击右上角“...”可选择“添加到我的小程序”，即可更加快捷地进入游戏。舟车劳顿，我们为您准备了一些元宝，请及时领取。";
                MailManager.sendMail(player.getUserId(), eMailType.SYSTEM.getValue(), PropertyHelper.parsePropertyToString(reward), content, title);
                log.info("新玩家关注邮件奖励，userId: {}", player.getUserId());
            }
        }
    }

    private void editLimitReward(GamePlayer player) {
        if(player.getUserInfo().getLastLoginTime() <= 0) {
            //编辑限制
            GameEditLimit gameEditLimit = GameEditLimitMgr.getGameEditLimit(0);
            if (null != gameEditLimit) {
                ServerInfo serverInfo = ServerListMgr.getServerInfo(GameServer.getInstance().getServerId());
                if (serverInfo.getServerType() == 1) {//提审服不发开服邮件
                    return;
                }
                long nowTime = System.currentTimeMillis();
                if (nowTime >= gameEditLimit.getLimitEditStartTime() && nowTime < gameEditLimit.getLimitEditEndTime()) {
                    String title = "文本编辑功能临时关闭通知";
                    String content = "亲爱的掌柜，由于服务器聊天系统优化升级，需要临时关闭游戏内文本编辑的相关功能，优化升级后恢复。" +
                            "由此给您带来的不便深感歉意，感谢掌柜的理解与支持!";
                    String reward = "119022=1;110062=2;110031=10;110017=5;110000=1;110084=1;110013=1;110090=1";
                    if (!StringUtils.isNullOrEmpty(gameEditLimit.getReplaceContent())) {
                        String[] replaceArr = gameEditLimit.getReplaceContent().split("\\|");
                        if (replaceArr.length > 0) {
                            title = replaceArr[0];
                        }
                        if (replaceArr.length > 1) {
                            content = replaceArr[1];
                        }
                        if (replaceArr.length > 2) {
                            reward = replaceArr[2];
                        }
                    }
                    Property property = PropertyHelper.parseStringToProperty(reward);
                    MailManager.sendMail(player.getUserId(), eMailType.SYSTEM.getValue(), PropertyHelper.parsePropertyToString(property), content, title);
                }
            }
        }
    }

    /**
    * 描述：发改名卡
    * 作者：zrq
    * 时间：2023/4/12
    * 参数：

    * 返回值：
    **/
    private void sendChangeNicknameGoods(GamePlayer player){
        String mailTitle = MultipleLanguageMgr.getContent(MailManager.USER_NAME_CHANGE_TITLE, player.getLanguage());
        String mailContent = MultipleLanguageMgr.getContent(MailManager.USER_NAME_CHANGE_CONTENT, player.getLanguage());
        Property property = new Property(GameConfig.GAME_ITEM_CHANGE_NAME, BigInteger.ONE);
        MailManager.sendMail(player.getUserId(), eMailType.SYSTEM.getValue(), PropertyHelper.parsePropertyToString(property), mailContent, mailTitle);
    }

    public void notifyCoupon(GamePlayer player){
        CouponNotifyArgs notifyArgs = new CouponNotifyArgs();
        notifyArgs.setLogin(true);
        player.notifyListener(eGamePlayerEventType.CouponTrigger.getValue(), notifyArgs);
    }
}
